home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 1997 May & June
/
Amiga-CD 1997 #5-6.iso
/
emulatoren
/
frodov2.4
/
src
/
6526.asm
< prev
next >
Wrap
Assembly Source File
|
1997-01-03
|
29KB
|
1,532 lines
*
* 6526.asm - CIA-Emulation
*
* Copyright (C) 1994-1996 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Funktionsweise/Periodic:
* - Für jede (simulierte) C64-Rasterzeile wird vom 6510-Task die Routine
* Periodic6526 aufgerufen, die die Timer herunterzählt und ggf.
* Interrupts auslöst
*
* Timer/Latches:
* - Die Bytefolge im Register-File ist gegenüber dem echten 6526 umgekehrt,
* das wird aber bei den WriteTo6526- und ReadFrom6526-Routinen wieder
* ausgeglichen
*
* TOD-Clocks:
* - Die TODs werden synchron mit dem VBlank gezählt. Es wird also ein
* 50Hz-Eingangssignal simuliert.
*
* Tastaturabfrage:
* - Das Feld KeyMatrix enthält für jede Taste entsprechend der C64-
* Tastaturmatrix ein Bit (0: Taste gedrückt, 1: Taste nicht gedrückt).
* InvKeyMatrix ist dieselbe Matrix mit vertauschten Zeilen und Spalten
* (für "inverse" Tastaturabfragen).
* - Bei Lesezugriffen aus CIA-A, Port A/B werden entsprechend der aktiven
* (ausgewählten) Zeilen der Tastatur die entsprechenden Bits aus der
* Tastaturmatrix zusammengestellt
* - F9 löst einen NMI aus (Restore), F10 einen RESET
*
* Joystickabfrage:
* - Die Joysticks werden im VBlank abgefragt, wenn auch die TODs
* gezählt werden
*
* Lightpen:
* - Bei jedem Schreibzugriff auf PRB/DDRB von CIA-A wird geprüft, ob die
* Lightpen-Leitung (Bit 4) einen Übergang 1->0 macht. In diesem Fall
* wird der VIC informiert.
*
* Inkompatibilitäten:
* - Die TOD-Clock sollte bei einem Lesezugriff nicht angehalten,
* sondern gelatcht werden
* - Der SDR-Interrupt ist nicht echt
*
MACHINE 68020
XREF ShowPrefs ;Main.asm
XREF _ciaaprb
XREF _ciaaddrb
XREF IntIsNMI ;6510.asm
XREF IntIsCIAIRQ
XREF NMIState
XREF Peri6526Cont
XREF ChangedVA ;6569.asm
XREF TriggerLightpen
XREF IECIsOpen ;IEC.asm
XDEF Reset6526
XDEF _GetCIA1Dump
XDEF _GetCIA2Dump
XDEF ReadFrom6526A
XDEF ReadFrom6526B
XDEF WriteTo6526A
XDEF WriteTo6526B
XDEF Periodic6526
XDEF ChangedKeys
XDEF CountTODs
XDEF _KeyPressed
XDEF CIACycles ;Prefs
XDEF Joystick1On
XDEF Joystick2On
XDEF JoystickSwap
XDEF KeyboardYZ
SECTION "text",CODE
**
** Definitionen
**
; CIA-Register
PRA = 0
PRB = 1
DDRA = 2
DDRB = 3
TAHI = 4 ;Timer-Wert A
TALO = 5 ;Achtung: Umgekehrte Bytefolge!
TBHI = 6 ;Timer-Wert B
TBLO = 7
TOD10THS = 8
TODSEC = 9
TODMIN = 10
TODHR = 11
SDR = 12
ICR = 13 ;Interrupt-Data
CRA = 14
CRB = 15
; Zusätzliche Register
LTCHA = 16 ;Timer-Latch A
LTCHB = 18 ;Timer-Latch B
INTMASK = 20 ;Interrupt-Enable
TODHALT = 21 ;TOD zwecks Beschreiben/Auslesen gestoppt
ALM10THS = 22 ;Alarmzeit
ALMSEC = 23
ALMMIN = 24
ALMHR = 25
TODDIV = 26 ;TOD-Frequenzteiler
TACNTPHI2 = 27 ;Timer A läuft und zählt Phi2
TBCNTPHI2 = 28 ;Timer B läuft und zählt Phi2
TBCNTTA = 29 ;Timer B läuft und zählt Unterläufe von Timer A
PREVLP = 30 ;Voriger Zustand der Lightpen-Leitung (nur CIA-A)
RPC EQUR a6 ;PC (32-Bit Amiga-Adresse, untere 16 Bit
; stimmen mit C64-PC überein)
**
** CIAs zurücksetzen
**
; CIA-A
Reset6526 lea Registers1,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
clr.b TBCNTTA(a0)
move.b #$10,PREVLP(a0) ;Lightpen-Leitung ist High
move.b #$ff,Joystick1 ;Joystick inaktiv
move.b #$ff,Joystick2
move.b #$ff,Joystick2Key
; CIA-B
lea Registers2,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
clr.b TBCNTTA(a0)
; Tastaturmatrix löschen
moveq #-1,d0
move.l d0,KeyMatrix
move.l d0,KeyMatrix+4
move.l d0,InvKeyMatrix
move.l d0,InvKeyMatrix+4
; VIC-Bank 0 einstellen
moveq #0,d0
bra ChangedVA
**
** CIA-Status in Datenstruktur schreiben
**
_GetCIA1Dump lea Registers1,a0
bra GetCIADump
_GetCIA2Dump lea Registers2,a0
GetCIADump move.l 4(sp),a1
move.l (a0),(a1)+
move.b TALO(a0),(a1)+ ;Wegen umgekehrter Bytefolge
move.b TAHI(a0),(a1)+
move.b TBLO(a0),(a1)+
move.b TBHI(a0),(a1)+
move.l TOD10THS(a0),(a1)+
move.l SDR(a0),(a1)+
move.b LTCHA+1(a0),(a1)+
move.b LTCHA(a0),(a1)+
move.b LTCHB+1(a0),(a1)+
move.b LTCHB(a0),(a1)+
move.l ALM10THS(a0),(a1)+
move.b INTMASK(a0),(a1)
rts
**
** Tastaturbelegung geändert, Y und Z sortieren
**
ChangedKeys tst.w KeyboardYZ
bne 1$
move.l #$00010004,KeyPatch1
move.l #$00030001,KeyPatch2
rts
1$ move.l #$00030001,KeyPatch1
move.l #$00010004,KeyPatch2
rts
**
** In ein CIA-A-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
WriteTo6526A lea Registers1,a0
move.l WriteTabA(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabA dc.l WrNormal
dc.l WrAPRB
dc.l WrNormal
dc.l WrADDRB
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrASDR
dc.l WrAICR
dc.l WrCRA
dc.l WrCRB
WrNormal move.b d1,(a0,d0.w)
rts
WrAPRB move.b d1,PRB(a0)
bra CheckLP
WrADDRB move.b d1,DDRB(a0)
CheckLP move.b DDRB(a0),d0 ;Lightpen-Leitung
not.b d0
or.b PRB(a0),d0
and.b #$10,d0
cmp.b PREVLP(a0),d0 ;Änderung?
beq 1$
move.b d0,PREVLP(a0) ;Ja, negative Flanke?
bne 1$
bra TriggerLightpen ;Ja, LP triggern
1$ rts
WrTALO move.b d1,LTCHA+1(a0)
rts
WrTAHI move.b d1,LTCHA(a0)
btst #0,CRA(a0) ;Timer A gestoppt?
bne 1$
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ rts
WrTBLO move.b d1,LTCHB+1(a0)
rts
WrTBHI move.b d1,LTCHB(a0)
btst #0,CRB(a0) ;Timer B gestoppt?
bne 1$
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ rts
WrTOD10THS and.b #$0f,d1
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TOD10THS(a0)
rts
1$ move.b d1,ALM10THS(a0)
rts
WrTODSEC and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODSEC(a0)
rts
1$ move.b d1,ALMSEC(a0)
rts
WrTODMIN and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODMIN(a0)
rts
1$ move.b d1,ALMMIN(a0)
rts
WrTODHR and.b #$9f,d1
st.b TODHALT(a0) ;TOD anhalten
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODHR(a0)
rts
1$ move.b d1,ALMHR(a0)
rts
WrASDR move.b d1,SDR(a0)
or.b #$08,ICR(a0) ;SDR-Interrupt auslösen
btst #3,INTMASK(a0)
beq 1$
or.b #$80,ICR(a0)
st.b IntIsCIAIRQ
1$ rts
WrAICR move.b -3(RPC),d0 ;Opcode lesen
cmp.b #$9d,d0 ;STA Abs,X
beq 11$
cmp.b #$99,d0 ;STA Abs,Y
bne 10$
11$ clr.b ICR(a0) ;IRQ bei indizierter Adressierung löschen
clr.b IntIsCIAIRQ
10$ bclr #7,d1 ;S/C-Bit löschen
bne 1$ ;War es gesetzt?
not.b d1 ;Nein, Bits zum Löschen negieren
and.b d1,INTMASK(a0) ;Und Bits löschen
bra 2$
1$ or.b d1,INTMASK(a0) ;Bits setzen
2$
move.b ICR(a0),d0 ;Anstehende Interrupts erlaubt?
and.b INTMASK(a0),d0
and.b #$1f,d0
beq 3$
or.b #$80,ICR(a0) ;Ja, IRQ auslösen
st.b IntIsCIAIRQ
3$ rts ;Nein
WrCRA bclr #4,d1 ;Force load?
beq 1$
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ move.b d1,CRA(a0)
and.b #$21,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TACNTPHI2(a0) ;Ja, Flag setzen
rts
WrCRB bclr #4,d1 ;Force load?
beq 1$
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ move.b d1,CRB(a0)
and.b #$61,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TBCNTPHI2(a0) ;Ja, Flag setzen
cmp.b #$41,d1 ;Läuft er und zählt Unterläuft von Timer A?
seq.b TBCNTTA(a0) ;Ja, Flag setzen
rts
**
** In ein CIA-B-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
WriteTo6526B lea Registers2,a0
move.l WriteTabB(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabB dc.l WrBPRA
dc.l WrNormal
dc.l WrBDDRA
dc.l WrNormal
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrBSDR
dc.l WrBICR
dc.l WrCRA
dc.l WrCRB
WrBPRA move.b d1,PRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, Port setzen
beq WrBNewVA
move.b d1,_ciaaprb
bra WrBNewVA
WrBDDRA move.b d1,DDRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, DDR setzen
beq WrBNewVA
move.b d1,_ciaaddrb
WrBNewVA move.b DDRA(a0),d0 ;VA extrahieren
not.b d0
or.b PRA(a0),d0
not.b d0
and.b #$03,d0
bra ChangedVA ;Und dem VIC mitteilen
WrBSDR move.b d1,SDR(a0)
or.b #$08,ICR(a0) ;SDR-Interrupt auslösen
btst #3,INTMASK(a0)
beq 1$
or.b #$80,ICR(a0)
tst.b NMIState
bne 1$
st.b NMIState
st.b IntIsNMI
1$ rts
WrBICR move.b -3(RPC),d0 ;Opcode lesen
cmp.b #$9d,d0 ;STA Abs,X
beq 11$
cmp.b #$99,d0 ;STA Abs,Y
bne 10$
11$ clr.b ICR(a0) ;IRQ bei indizierter Adressierung löschen
clr.b NMIState
10$ bclr #7,d1 ;S/C-Bit löschen
bne 1$ ;War es gesetzt?
not.b d1 ;Nein, Bits zum Löschen negieren
and.b d1,INTMASK(a0) ;Und Bits löschen
bra 2$
1$ or.b d1,INTMASK(a0) ;Bits setzen
2$
move.b ICR(a0),d0 ;Anstehende Interrupts erlaubt?
and.b INTMASK(a0),d0
and.b #$1f,d0
beq 3$
or.b #$80,ICR(a0) ;Ja, NMI auslösen
tst.b NMIState
bne 3$
st.b NMIState
st.b IntIsNMI
3$ rts ;Nein
**
** Aus einem CIA-A-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
ReadFrom6526A lea Registers1,a0
move.l ReadTabA(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
ReadTabA dc.l RdAPRA
dc.l RdAPRB
dc.l RdANormal
dc.l RdANormal
dc.l RdATALO
dc.l RdATAHI
dc.l RdATBLO
dc.l RdATBHI
dc.l RdATOD10THS
dc.l RdANormal
dc.l RdANormal
dc.l RdATODHR
dc.l RdANormal
dc.l RdAICR
dc.l RdANormal
dc.l RdANormal
RdANormal move.b (a0,d0.w),d0
rts
RdAPRA lea InvKeyMatrix,a1
move.b DDRB(a0),d1 ;Tastaturabfrage
not.b d1
or.b PRB(a0),d1
and.b Joystick1,d1
move.b DDRA(a0),d0
not.b d0
or.b PRA(a0),d0
lsr.b #1,d1 ;Alle aktiven Spalten dazuANDen
bcs 1$
and.b (a1),d0
1$ lsr.b #1,d1
bcs 2$
and.b 1(a1),d0
2$ lsr.b #1,d1
bcs 3$
and.b 2(a1),d0
3$ lsr.b #1,d1
bcs 4$
and.b 3(a1),d0
4$ lsr.b #1,d1
bcs 5$
and.b 4(a1),d0
5$ lsr.b #1,d1
bcs 6$
and.b 5(a1),d0
6$ lsr.b #1,d1
bcs 7$
and.b 6(a1),d0
7$ lsr.b #1,d1
bcs 8$
and.b 7(a1),d0
8$
and.b Joystick2,d0
rts
RdAPRB lea KeyMatrix,a1
move.b DDRA(a0),d1 ;Tastaturabfrage
not.b d1
or.b PRA(a0),d1
and.b Joystick2,d1
move.b DDRB(a0),d0
not.b d0
lsr.b #1,d1 ;Alle aktiven Reihen dazuANDen
bcs 1$
and.b (a1),d0
1$ lsr.b #1,d1
bcs 2$
and.b 1(a1),d0
2$ lsr.b #1,d1
bcs 3$
and.b 2(a1),d0
3$ lsr.b #1,d1
bcs 4$
and.b 3(a1),d0
4$ lsr.b #1,d1
bcs 5$
and.b 4(a1),d0
5$ lsr.b #1,d1
bcs 6$
and.b 5(a1),d0
6$ lsr.b #1,d1
bcs 7$
and.b 6(a1),d0
7$ lsr.b #1,d1
bcs 8$
and.b 7(a1),d0
8$
move.b PRB(a0),d1
and.b DDRB(a0),d1
or.b d1,d0
and.b Joystick1,d0
rts
RdATALO move.b TALO(a0),d0 ;Weil die Timer im Registerfile
rts ;als big-endian gespeichert sind
RdATAHI move.b TAHI(a0),d0
rts
RdATBLO move.b TBLO(a0),d0
rts
RdATBHI move.b TBHI(a0),d0
rts
RdATOD10THS move.b TOD10THS(a0),d0
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
rts
RdATODHR st.b TODHALT(a0) ;TOD anhalten
move.b TODHR(a0),d0
rts
RdAICR move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
clr.b IntIsCIAIRQ ;IRQ zurücknehmen
rts
**
** Aus einem CIA-B-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
** Darf das obere Wort von d0 und d1 nicht verändern!
**
ReadFrom6526B lea Registers2,a0
move.l ReadTabB(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
ReadTabB dc.l RdBPRA
dc.l RdBPRB
dc.l RdBNormal
dc.l RdBNormal
dc.l RdBTALO
dc.l RdBTAHI
dc.l RdBTBLO
dc.l RdBTBHI
dc.l RdBTOD10THS
dc.l RdBNormal
dc.l RdBNormal
dc.l RdBTODHR
dc.l RdBNormal
dc.l RdBICR
dc.l RdBNormal
dc.l RdBNormal
RdBNormal move.b (a0,d0.w),d0
rts
RdBPRA move.b DDRA(a0),d0 ;Floppy/VA
not.b d0
or.b PRA(a0),d0
tst.b IECIsOpen ;Wenn IEC aktiv ist, davon lesen
beq 1$
and.b #$03,d0
move.b _ciaaprb,d1
and.b #$fc,d1
or.b d1,d0
1$ rts
RdBPRB move.b DDRB(a0),d0 ;Userport
not.b d0 ;Eingabebits immer 1
or.b PRB(a0),d0
rts
RdBTALO move.b TALO(a0),d0 ;Weil die Timer im Registerfile
rts ;als big-endian gespeichert sind
RdBTAHI move.b TAHI(a0),d0
rts
RdBTBLO move.b TBLO(a0),d0
rts
RdBTBHI move.b TBHI(a0),d0
rts
RdBTOD10THS move.b TOD10THS(a0),d0
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
rts
RdBTODHR st.b TODHALT(a0) ;TOD anhalten
move.b TODHR(a0),d0
rts
RdBICR move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
clr.b NMIState ;NMI zurücknehmen
rts
**
** Wird jede Rasterzeile einmal aufgerufen
**
*
* CIA-A
* d1: ICR
* d2: INTMASK
* d3: CIACycles
*
Periodic6526 lea Registers1,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
move.w CIACycles,d3
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATADone
sub.w d3,TAHI(a0) ;Ja, herabzählen
bcc CiaATADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaATANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaATADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaATBUnderflow ;Untergelaufen?
CiaATADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATBDone
sub.w d3,TBHI(a0) ;Ja, herabzählen
bcc CiaATBDone ;Unterlauf?
CiaATBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaATBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaATBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaATBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
*
* CIA-B
* d1: ICR
* d2: INTMASK
* d3: CIACycles
*
lea Registers2,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTADone
sub.w d3,TAHI(a0) ;Ja, herabzählen
bcc CiaBTADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaBTANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
st.b NMIState ;Nein, NMI auslösen
st.b IntIsNMI
1$
CiaBTANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaBTADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaBTBUnderflow ;Untergelaufen?
CiaBTADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTBDone
sub.w d3,TBHI(a0) ;Ja, herabzählen
bcc CiaBTBDone ;Unterlauf?
CiaBTBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaBTBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
st.b NMIState ;Nein, NMI auslösen
st.b IntIsNMI
1$
CiaBTBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaBTBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaBTBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
; In 6510-Task zurückspringen
bra Peri6526Cont
**
** TODs zählen
**
*
* CIA-A
*
CountTODs lea Registers1,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaATODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaATOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaATODLoaded
CiaATOD60Hz move.b #5,TODDIV(a0)
CiaATODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaATODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaATODDone
and.b #$80,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaATODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaATODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaATODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATODNoIRQ move.b d0,ICR(a0)
CiaATODNop
*
* CIA-B
*
lea Registers2,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaBTODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaBTOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaBTODLoaded
CiaBTOD60Hz move.b #5,TODDIV(a0)
CiaBTODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaBTODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaBTODDone
and.b #$80,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaBTODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaBTODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaBTODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
st.b NMIState ;Nein, NMI auslösen
st.b IntIsNMI
1$
CiaBTODNoIRQ move.b d0,ICR(a0)
CiaBTODNop
*
* Joystickabfrage
*
lea Registers1,a0
; Port 1
move.b #$ff,d2 ;Vorgabe: Joystick inaktiv
tst.w Joystick1On(pc)
beq 15$
btst #6,$bfe001 ;Feuerknopf
bne 11$
bclr #4,d2
11$ move.w $dff00a,d0
btst #1,d0 ;Rechts
beq 12$
bclr #3,d2
12$ btst #9,d0 ;Links
beq 13$
bclr #2,d2
13$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 14$
bclr #1,d2
14$ btst #9,d0 ;Hoch
beq 15$
bclr #0,d2
15$ move.b d2,Joystick1
; Port 2
move.b Joystick2Key,d2 ;Vorgabe: Zehnerblock-Emulation
tst.w Joystick2On(pc)
beq 25$
btst #7,$bfe001 ;Feuerknopf
bne 21$
bclr #4,d2
21$ move.w $dff00c,d0
btst #1,d0 ;Rechts
beq 22$
bclr #3,d2
22$ btst #9,d0 ;Links
beq 23$
bclr #2,d2
23$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 24$
bclr #1,d2
24$ btst #9,d0 ;Hoch
beq 25$
bclr #0,d2
25$ move.b d2,Joystick2
; Joysticks vertauschen?
tst.w JoystickSwap(pc)
beq 30$
move.b Joystick1,d0
move.b Joystick2,Joystick1
move.b d0,Joystick2
30$ rts
**
** Taste wurde gedrückt
**
KeyDown MACRO
bclr #\1,\2(a0)
bclr #\2,\1(a1)
ENDM
KeyUp MACRO
bset #\1,\2(a0)
bset #\2,\1(a1)
ENDM
_KeyPressed move.l 4(sp),d0
lea KeyMatrix,a0
lea InvKeyMatrix,a1
bclr #7,d0 ;KeyUp/KeyDown
bne KeyUp
cmp.b #$40,d0
bhs KeyDownSpecial
and.w #$003f,d0 ;$00..$3f
cmp.b #$0f,d0 ;Joystick-Emulation
beq KeyDownJoyFire
cmp.b #$1d,d0
beq KeyDownJoyDL
cmp.b #$1e,d0
beq KeyDownJoyDown
cmp.b #$1f,d0
beq KeyDownJoyDR
cmp.b #$2d,d0
beq KeyDownJoyLeft
cmp.b #$2e,d0
beq KeyDownJoyFire
cmp.b #$2f,d0
beq KeyDownJoyRight
cmp.b #$3d,d0
beq KeyDownJoyUL
cmp.b #$3e,d0
beq KeyDownJoyUp
cmp.b #$3f,d0
beq KeyDownJoyUR
movem.w KeyTable(pc,d0.w*4),d0/d1
bclr d1,(a0,d0.w)
bclr d0,(a1,d1.w)
rts
KeyUp cmp.b #$40,d0
bhs KeyUpSpecial
and.w #$003f,d0 ;$00..$3f
cmp.b #$0f,d0 ;Joystick-Emulation
beq KeyUpJoyFire
cmp.b #$1d,d0
beq KeyUpJoyDL
cmp.b #$1e,d0
beq KeyUpJoyDown
cmp.b #$1f,d0
beq KeyUpJoyDR
cmp.b #$2d,d0
beq KeyUpJoyLeft
cmp.b #$2e,d0
beq KeyUpJoyFire
cmp.b #$2f,d0
beq KeyUpJoyRight
cmp.b #$3d,d0
beq KeyUpJoyUL
cmp.b #$3e,d0
beq KeyUpJoyUp
cmp.b #$3f,d0
beq KeyUpJoyUR
movem.w KeyTable(pc,d0.w*4),d0/d1
bset d1,(a0,d0.w)
bset d0,(a1,d1.w)
KeyNOP rts
KeyDownSpecial sub.b #$40,d0
cmp.b #$20,d0
bhs KeyDownMod
and.w #$1f,d0 ;$40..$5f
jmp ([KeyDownSpecTab,pc,d0.w*4])
KeyDownMod sub.b #$20,d0
cmp.b #$08,d0
bhs KeyNOP
and.w #$07,d0 ;$60..$67
cmp.w #$07,d0 ;Amiga rechts ignorieren
beq 1$
movem.w KeyModTable(pc,d0.w*4),d0/d1
bclr d1,(a0,d0.w)
bclr d0,(a1,d1.w)
1$ rts
KeyUpSpecial sub.b #$40,d0
cmp.b #$20,d0
bhs KeyUpMod
and.w #$1f,d0 ;$40..$5f
jmp ([KeyUpSpecTab,pc,d0.w*4])
KeyUpMod sub.b #$20,d0
cmp.b #$08,d0
bhs KeyNOP
and.w #$07,d0 ;$60..$67
cmp.w #$07,d0 ;Amiga rechts ignorieren
beq 1$
movem.w KeyModTable(pc,d0.w*4),d0/d1
bset d1,(a0,d0.w)
bset d0,(a1,d1.w)
1$ rts
KeySpaceD KeyDown 4,7
rts
KeySpaceU KeyUp 4,7
rts
KeyBackD KeyDown 0,0
rts
KeyBackU KeyUp 0,0
rts
KeyTabD KeyDown 7,7
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
st.b IntIsNMI ;Nein, NMI auslösen
1$ rts
KeyTabU KeyUp 7,7
rts
KeyEnterD
KeyReturnD KeyDown 1,0
rts
KeyEnterU
KeyReturnU KeyUp 1,0
rts
KeyEscD KeyDown 7,7
rts
KeyEscU KeyUp 7,7
rts
KeyDeleteD KeyDown 3,6
rts
KeyDeleteU KeyUp 3,6
rts
KeyUpD KeyDown 4,6
KeyDown 7,0
rts
KeyUpU KeyUp 4,6
KeyUp 7,0
rts
KeyDownD KeyDown 7,0
rts
KeyDownU KeyUp 7,0
rts
KeyRightD KeyDown 2,0
rts
KeyRightU KeyUp 2,0
rts
KeyLeftD KeyDown 4,6
KeyDown 2,0
rts
KeyLeftU KeyUp 4,6
KeyUp 2,0
rts
KeyF1D KeyDown 4,0
rts
KeyF1U KeyUp 4,0
rts
KeyF3D KeyDown 5,0
rts
KeyF3U KeyUp 5,0
rts
KeyF5D KeyDown 6,0
rts
KeyF5U KeyUp 6,0
rts
KeyF7D KeyDown 3,0
rts
KeyF7U KeyUp 3,0
rts
KeyF2D KeyDown 4,6
KeyDown 4,0
rts
KeyF2U KeyUp 4,6
KeyUp 4,0
rts
KeyF4D KeyDown 4,6
KeyDOwn 5,0
rts
KeyF4U KeyUp 4,6
KeyUp 5,0
rts
KeyF6D KeyDown 4,6
KeyDown 6,0
rts
KeyF6U KeyUp 4,6
KeyUp 6,0
rts
KeyF8D KeyDown 4,6
KeyDown 3,0
rts
KeyF8U KeyUp 4,6
KeyUp 3,0
rts
KeyF9D tst.b NMIState ;NMI schon ausgelöst?
bne 1$
st.b IntIsNMI ;Nein, NMI auslösen
1$ rts
KeyNKAsterD tst.w KeyboardYZ
bne 1$
KeyDown 1,6 ;*
rts
1$ KeyDown 5,6 ;=
rts
KeyNKAsterU tst.w KeyboardYZ
bne 1$
KeyUp 1,6
rts
1$ KeyUp 5,6
rts
KeyNKSlashD tst.w KeyboardYZ
bne 1$
KeyDown 7,6 ;/
rts
1$ KeyDown 6,6 ;^
rts
KeyNKSlashU tst.w KeyboardYZ
bne 1$
KeyUp 7,6
rts
1$ KeyUp 6,6
rts
KeyNKLeftParD KeyDown 4,6 ;[
KeyDown 5,5
rts
KeyNKLeftParU KeyUp 4,6
KeyUp 5,5
rts
KeyNKRightParD KeyDown 4,6 ;]
KeyDown 2,6
rts
KeyNKRightParU KeyUp 4,6
KeyUp 2,6
rts
; Joystick-Emulation
KeyDownJoyUp bclr #0,Joystick2Key
rts
KeyDownJoyDown bclr #1,Joystick2Key
rts
KeyDownJoyLeft bclr #2,Joystick2Key
rts
KeyDownJoyRight bclr #3,Joystick2Key
rts
KeyDownJoyUL bclr #0,Joystick2Key
bclr #2,Joystick2Key
rts
KeyDownJoyUR bclr #0,Joystick2Key
bclr #3,Joystick2Key
rts
KeyDownJoyDL bclr #1,Joystick2Key
bclr #2,Joystick2Key
rts
KeyDownJoyDR bclr #1,Joystick2Key
bclr #3,Joystick2Key
rts
KeyDownJoyFire bclr #4,Joystick2Key
rts
KeyUpJoyUp bset #0,Joystick2Key
rts
KeyUpJoyDown bset #1,Joystick2Key
rts
KeyUpJoyLeft bset #2,Joystick2Key
rts
KeyUpJoyRight bset #3,Joystick2Key
rts
KeyUpJoyUL bset #0,Joystick2Key
bset #2,Joystick2Key
rts
KeyUpJoyUR bset #0,Joystick2Key
bset #3,Joystick2Key
rts
KeyUpJoyDL bset #1,Joystick2Key
bset #2,Joystick2Key
rts
KeyUpJoyDR bset #1,Joystick2Key
bset #3,Joystick2Key
rts
KeyUpJoyFire bset #4,Joystick2Key
rts
**
** Datenbereich
**
CNOP 0,4
Registers1 ds.b 32 ;CIA-A-Register
Registers2 ds.b 32 ;CIA-B-Register
CIACycles dc.w 0 ;Anzahl Phi2-Zyklen pro Rasterzeile (für Timer)
Joystick1On dc.w 0 ;Joystick an Port 1 wird abgefragt
Joystick2On dc.w 0 ;Joystick an Port 2 wird abgefragt
XDEF _JoystickSwap
_JoystickSwap
JoystickSwap dc.w 0 ;Joysticks vertauschen
KeyboardYZ dc.w 0 ;Amerikanische Tastaturbelegung
Joystick1 dc.b 0 ;Joystick 1 AND-Wert
Joystick2 dc.b 0 ;Joystick 2 AND-Wert
Joystick2Key dc.b 0 ;Joystick 2 AND-Wert für Emulation über Zehnerblock
; Tastaturübersetzungstabelle:
; Für jeden Amiga-RawKey Spalte und Zeile in der KeyMatrix
CNOP 0,4
KeyTable dc.w 7,1 ;` -> <-
dc.w 7,0 ;1
dc.w 7,3 ;2
dc.w 1,0 ;3
dc.w 1,3 ;4
dc.w 2,0 ;5
dc.w 2,3 ;6
dc.w 3,0 ;7
dc.w 3,3 ;8
dc.w 4,0 ;9
dc.w 4,3 ;0
dc.w 5,0 ;ß -> +
dc.w 5,3 ;´ -> -
dc.w 6,0 ;\ -> £
dc.w 0,0
dc.w 4,3 ;NP 0
dc.w 7,6 ;Q
dc.w 1,1 ;W
dc.w 1,6 ;E
dc.w 2,1 ;R
dc.w 2,6 ;T
KeyPatch1 dc.w 1,4 ;Y -> Z
dc.w 3,6 ;U
dc.w 4,1 ;I
dc.w 4,6 ;O
dc.w 5,1 ;P
dc.w 5,6 ;ü -> @
dc.w 6,1 ;+ -> *
dc.w 0,0
dc.w 7,0 ;NP 1
dc.w 7,3 ;NP 2
dc.w 1,0 ;NP 3
dc.w 1,2 ;A
dc.w 1,5 ;S
dc.w 2,2 ;D
dc.w 2,5 ;F
dc.w 3,2 ;G
dc.w 3,5 ;H
dc.w 4,2 ;J
dc.w 4,5 ;K
dc.w 5,2 ;L
dc.w 5,5 ;ö -> :
dc.w 6,2 ;ä -> ;
dc.w 6,5 ;# -> =
dc.w 0,0
dc.w 1,3 ;NP 4
dc.w 2,0 ;NP 5
dc.w 2,3 ;NP 6
dc.w 6,6 ;< -> ^
KeyPatch2 dc.w 3,1 ;Z -> Y
dc.w 2,7 ;X
dc.w 2,4 ;C
dc.w 3,7 ;V
dc.w 3,4 ;B
dc.w 4,7 ;N
dc.w 4,4 ;M
dc.w 5,7 ;,
dc.w 5,4 ;.
dc.w 6,7 ;- -> /
dc.w 0,0
dc.w 5,4 ;NP .
dc.w 3,0 ;NP 7
dc.w 3,3 ;NP 8
dc.w 4,0 ;NP 9
KeyDownSpecTab dc.l KeySpaceD
dc.l KeyBackD
dc.l KeyTabD
dc.l KeyEnterD
dc.l KeyReturnD
dc.l KeyEscD
dc.l KeyDeleteD
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyUpD
dc.l KeyDownD
dc.l KeyRightD
dc.l KeyLeftD
dc.l KeyF1D
dc.l KeyF2D
dc.l KeyF3D
dc.l KeyF4D
dc.l KeyF5D
dc.l KeyF6D
dc.l KeyF7D
dc.l KeyF8D
dc.l KeyF9D
dc.l KeyNOP
dc.l KeyNKLeftParD
dc.l KeyNKRightParD
dc.l KeyNKSlashD
dc.l KeyNKAsterD
dc.l KeyNOP
dc.l KeyNOP
KeyUpSpecTab dc.l KeySpaceU
dc.l KeyBackU
dc.l KeyTabU
dc.l KeyEnterU
dc.l KeyReturnU
dc.l KeyEscU
dc.l KeyDeleteU
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyUpU
dc.l KeyDownU
dc.l KeyRightU
dc.l KeyLeftU
dc.l KeyF1U
dc.l KeyF2U
dc.l KeyF3U
dc.l KeyF4U
dc.l KeyF5U
dc.l KeyF6U
dc.l KeyF7U
dc.l KeyF8U
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNKLeftParU
dc.l KeyNKRightParU
dc.l KeyNKSlashU
dc.l KeyNKAsterU
dc.l KeyNOP
dc.l KeyNOP
KeyModTable dc.w 1,7 ;Shift left
dc.w 6,4 ;Shift right
dc.w 1,7 ;Caps lock -> Shift left
dc.w 7,2 ;Control
dc.w 7,5 ;Alt left -> C=
dc.w 7,5 ;Alt right -> C=
dc.w 7,5 ;Amiga left -> C=
dc.w 0,0 ;Amiga right
; Bit 7 6 5 4 3 2 1 0
; 0 CUD F5 F3 F1 F7 CLR RET DEL
; 1 SHL E S Z 4 A W 3
; 2 X T F C 6 D R 5
; 3 V U H B 8 G Y 7
; 4 N O K M 0 J I 9
; 5 , @ : . - L P +
; 6 / ^ = SHR HOM ; * £
; 7 R/S Q C= SPC 2 CTL <- 1
KeyMatrix ds.b 8 ;C64-Tastaturmatrix pro Taste ein Bit
;0: Taste gedrückt
InvKeyMatrix ds.b 8 ;Gespiegelte Tastaturmatrix
END